//*********************************************************
//
//    Copyright (c) Microsoft. All rights reserved.
//    This code is licensed under the Apache License, Version 2.0.
//    THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
//    ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
//    IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
//    PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************

namespace TridentAPI
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Microsoft.Research.DataLayer;
    using System.Windows.Controls;

    /// <summary>
    /// The type-initializer which will support the custom type display, serialize and deserialize features.
    /// </summary>
    public abstract class BaseTypeInitializer
    {
        /// <summary>
        /// Gets os sets the runtime for which this TypeInitializer will be supported.
        /// </summary>
        public abstract Runtime SupportedRuntime
        {
            get;
            set;
        }

        /// <summary>
        /// The custom type for which this initializer is used.
        /// </summary>
        public abstract Type CustomType
        {
            get;
            set;
        }

        /// <summary>
        /// Parameterless constructor. This will be invoked for runtime creation of objects.
        /// Hence all the initialization code needs to be done here.
        /// </summary>
        public BaseTypeInitializer()
        {
        }

        /// <summary>
        /// This method will return the the UI control for initializing the type
        /// The host application can then decide how to host the UI. The control
        /// returned will be different for different run time environments. The
        /// returned control should be a member variable of the class that
        /// implements the abstract class. Doing this will make sure that the values 
        /// set in the control are availalbe to this class.
        /// </summary>
        /// <returns>UI control for initializing the type.</returns>
        public abstract UserControl GetUIControl();
        
        /// <summary>
        /// This method will use the values set in the UI to create the instance
        /// of the type and return the reference to the instance.
        /// In the trident environment especially with the remote execution servcice 
        /// the GetValue method will be called at a different point in time. 
        /// </summary>
        /// <returns>The actual object that this initializer represents.</returns>
        public abstract object GetValue();

        /// <summary>
        /// This method will return the string representation of the type
        /// which will be used for short hand represenation of the object.
        /// If the type is not initialized then this method should return an
        /// empty string.
        /// </summary>
        /// <returns></returns>
        public abstract string GetStringValue();

        /// <summary>
        /// This method will be called by the host application to save the values
        /// set by the user in the UI.
        /// An implementation of this method should ideally save all the values
        /// that the user has set in the UI control in member variables.
        /// </summary>
        public abstract void SaveValuesIntoCustomObject();

        /// <summary>
        /// Checks if the current object is a valid value.
        /// </summary>
        /// <returns>
        /// True if valuid value, false otherwise.
        /// </returns>
        public abstract bool ContainsValidValue();

        /// <summary>
        /// Specifies if the object is empty. This is different from the validity check in the sense that an empty object can be a valid value,
        /// or an object might contain data, but the data might be invalid.
        /// </summary>
        /// <returns></returns>
        public abstract bool ContainsEmptyValue();

        /// <summary>
        /// Get the serialized version of the custom object. In case the custom object not 
        /// being serializable, implement custom logic which can again be understood in the corresponding
        /// deserialize method.
        /// </summary>
        /// <param name="customObj">
        /// The custom object which needs to be serialized.
        /// </param>
        /// <returns>
        /// The serialized string version.
        /// </returns>
        public virtual string GetSerializedVersion(object customObj)
        {
            return customObj.ToString();
        }

        /// <summary>
        /// Get the custom object by deserializing the passed value. the default representation returns null.
        /// </summary>
        /// <param name="serializedVal">
        /// The serialized version.
        /// </param>
        /// <returns>
        /// The custom object.
        /// </returns>
        public virtual object GetDeserializedVersion(string serializedVal)
        {
            return null;
        }
    }
}
